//
//  MainViewController.swift
//  Automobile
//
//  Created by erkebulan elzhan on 8/12/20.
//  Copyright © 2020 erkebulan elzhan. All rights reserved.
//

import UIKit
import SnapKit

protocol MainVCCellActionsDelegate: class {
    func openAdvert (advert: Post)
    func contactSeller (type: CarFooterCell.FooterContact)
    func openHistory ()
    func openKomplektations ()
    func openFullInfo ()
}

protocol MainVCCell: class {
    var delegate: MainVCCellActionsDelegate! { get set }
}

/* [Preivew] <-- Only Preview */

// MARK: - Base

final class MainViewController: UIViewController, Alertable {
    
    // MARK: - Outlets
    
    private lazy var tableView: UITableView = {
        let tableView = UITableView()
        tableView.delegate = self
        tableView.dataSource = self
        tableView.backgroundColor = .whiteBlueColor
        tableView.showsVerticalScrollIndicator = false
        tableView.separatorStyle = .none
        tableView.tableFooterView = UIView()
        self.registerCells(table: tableView)
        return tableView
    }()
    
    // [Preivew]
    private lazy var editBtn: UIButton = {
        let btn =  UIButton()
        btn.clipsToBounds = true
        btn.layer.cornerRadius = 15
        btn.backgroundColor = .lightBlueColor
        btn.setTitleColor(.blueColor, for: .normal)
        btn.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .medium)
        btn.setTitle("Редактировать", for: .normal)
        return btn
    }()
    
    // [Preivew]
    private lazy var submitBtn: UIButton = {
        let btn =  UIButton()
        btn.clipsToBounds = true
        btn.layer.cornerRadius = 15
        btn.backgroundColor = .blueColor
        btn.setTitleColor(.white, for: .normal)
        btn.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .medium)
        btn.setTitle("Далее", for: .normal)
        return btn
    }()
    
    private lazy var overlayView: UIView = {
        let _view = UIView()
        _view.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4)
        return _view
    }()
    
    private lazy var complaintView: ComplaintView = {
        let complaintView = ComplaintView()
        complaintView.delegate = self
        complaintView.setAdvertId(mainViewModel.post.id)
        return complaintView
    }()
    
    private var screenGesture: UITapGestureRecognizer?
    private var menuPopup: MenuPopup!
    private var spinnerView = SpinnerView()
    
    
    // MARK: - Props

    private lazy var mainViewModel: MainViewModel = {
        let viewModel = MainViewModel()
        viewModel.delegate = self
        viewModel.viewModelDelegate = self
        return viewModel
    }()
    
    private var contactCell: CarContactsCell!


    // MARK: - Public Methods
    
    public func setProps (post: Post? = nil, postID: Int? = nil, isPreview: Bool = false) {
        mainViewModel.post = post
        mainViewModel.postID = postID
        mainViewModel.isPreview = isPreview
    }
    
    
    // MARK: - Init

    override func viewDidLoad() {
        super.viewDidLoad()
        self.addViews()
        if mainViewModel.post != nil {
            mainViewModel.update()
        } else if mainViewModel.postID != nil {
            self.loadPost()
        }
        tableView.reloadData()
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "contactsUpdate"), object: nil)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "menuClick"), object: nil)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        self.navigationController?.navigationBar.backgroundColor = .whiteBlueColor
        self.navigationController?.navigationBar.defaultNavBar()
        self.navigationController?.navigationBar.prefersLargeTitles = true
        
        if mainViewModel.post != nil {
            self.setUpNav()
        }
        
        if (mainViewModel.isPreview) {
            NotificationCenter.default.addObserver(self, selector: #selector(getContactsCellUpdate(notification:)), name: NSNotification.Name(rawValue: "contactsUpdate"), object: nil)
        }
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        self.navigationController?.navigationBar.prefersLargeTitles = false
    }
}


// MARK: - User Actions

extension MainViewController {
    
    @objc private func navBtnClicked (sender: UIBarButtonItem) {
        if sender.tag == 0 {
            self.navigationController?.popViewController(animated: true)
        } else if sender.tag == 4 {
            self.navigationController?.dismiss(animated: true, completion: nil)
        } else if sender.tag == 3 {
            self.showPopup()
        } else if sender.tag == 2 {
            self.openShare()
        } else if sender.tag == 1{
            mainViewModel.addToFavorite()
        }
    }
    
    @objc private func onNext(sender: UIButton) {
        if let item = contactCell {
            let data = item.returnData()
            mainViewModel.updatePost(city: data?.city, name: data?.name, email: data?.email)
        }
    }
    
    @objc private func onEdit (sender: UIButton) {
        let editVc = EditViewController()
        editVc.post = mainViewModel.post
        self.navigationController?.pushViewController(editVc, animated: true)
    }
    
    @objc private func overlayDidTap (sender: UITapGestureRecognizer) {
        self.hidePopup()
    }
    
    @objc private func didSelectMenuItem (notification: NSNotification) {
        if let userInfo = notification.userInfo {
            if let menuItemIndex = userInfo["index"] as? Int {
                switch menuItemIndex {
                case 0:
                    self.openComments()
                default:
                    self.showComplaintView()
                }
            }
        }
    }
}


// MARK: - Private Methods

extension MainViewController: RegionViewControllerDelegate {
    
    func selectCity(city: [City]) {
        if mainViewModel.isPreview {
            mainViewModel.post.city = city.item(at: 0)
            if mainViewModel.items.firstIndex(where: { $0 is CarContactsCellConfigurator }) != nil {
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "setRegion"), object: nil, userInfo: ["region": city.item(at: 0) as Any])
            }
        }
    }
    
    // Callback From CarContacts Cell
    
    @objc private func getContactsCellUpdate (notification: NSNotification) {
        if let userInfo = notification.userInfo {
            if userInfo["isSelected"] as? Bool ?? false {
                self.openRegionVC()
            } else {
                self.selectCity(city: [])
            }
        }
    }
    
    private func callUser () {
        if let number = mainViewModel.post.contactNumbers?.first {
            if let url = URL(string: "tel://\(number)") {
                if #available(iOS 10, *) {
                    UIApplication.shared.open(url, options: [:], completionHandler:nil)
                } else {
                    UIApplication.shared.openURL(url)
                }
            } else {
                self.showAlert("Упс...", "У нас нет контактного номера данного пользователя")
            }
        } else {
            self.showAlert("Упс...", "У нас нет контактного номера данного пользователя")
        }
    }

    private func openRegionVC () {
        let regionsVC = RegionViewController()
        regionsVC.delegate = self
        self.navigationController?.pushViewController(regionsVC, animated: true)
    }
    
    private func openComments () {
        let commentsVC = CommentsViewController()
        commentsVC.advertID = mainViewModel.post.id
        self.navigationController?.pushViewController(commentsVC, animated: true)
        self.hidePopup()
    }
    
    private func openEditVC () {
        let editVC = EditViewController()
        editVC.post = mainViewModel.post
        self.navigationController?.pushViewController(editVC, animated: true)
    }
    
    private func handleViewAfterFetch () {
        self.setUpNav()
        tableView.reloadData()
    }
    
    private func openShare () {
        let items = [URL(string: "https://www.auto-nomad.kz/advert/\(mainViewModel.post.id)")!]
        let ac = UIActivityViewController(activityItems: items, applicationActivities: nil)
        present(ac, animated: true)
    }
    
    private func loadPost () {
        mainViewModel.loadPost()
    }
}

extension MainViewController: MainViewModelDelegate, ViewModelProtocol {
    func loadPost(post: Post) {
        self.handleViewAfterFetch()
    }
    
    func updatePost() {
        let adTypeSelectorVC = AdTypeController()
        adTypeSelectorVC.post = mainViewModel.post
        self.navigationController?.pushViewController(adTypeSelectorVC, animated: true)
    }
    
    func updateCities(cities: [City]?) {}
    
    func updateSpinner(showSpinner: Bool) {
        showSpinner ? spinnerView.startAnimating() : spinnerView.stopAnimating()
        view.isUserInteractionEnabled = !showSpinner
    }
    
    func didHappenError(error: RequestError) {
        self.alertError(error: error)
    }
    
    func updatePosts() {
        self.setUpNav()
    }
}



// MARK: - Table View

extension MainViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return mainViewModel.items.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let item = mainViewModel.items[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: type(of: item).reuseId)!
        item.configure(cell: cell, index: indexPath.row)
        cell.selectionStyle = .none
        
        if cell is MainVCCell {
            (cell as? MainVCCell)?.delegate = self
        }
        
        if cell is CarContactsCell {
            contactCell = cell as? CarContactsCell
        }
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        if mainViewModel.isPreview {
            let view = UIView (frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 180))
            view.backgroundColor = .whiteBlueColor
            
            view.addSubview(editBtn)
            view.addSubview(submitBtn)
            
            editBtn.addTarget(self, action: #selector(onEdit(sender:)), for: .touchUpInside)
            submitBtn.addTarget(self, action: #selector(onNext(sender:)), for: .touchUpInside)
            
            submitBtn.snp.makeConstraints { (make) in
                make.leading.trailing.equalToSuperview().inset(16)
                make.bottom.equalToSuperview().offset(-20)
                make.height.equalTo(44)
            }
            editBtn.snp.makeConstraints { (make) in
                make.bottom.equalTo(submitBtn.snp.top).offset(-8)
                make.height.equalTo(44)
                make.leading.trailing.equalToSuperview().inset(16)
            }
            
            return view
        } else {
            return nil
        }
    }
    
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return mainViewModel.isPreview ? 100 : 0
    }
    
}

// MARK: - Cell Actions

extension MainViewController: MainVCCellActionsDelegate {
   
    func openKomplektations() {
        let komplektsVC = KomplektsViewController()
        komplektsVC.carId = mainViewModel.post.car.id
        self.navigationController?.pushViewController(komplektsVC, animated: true)
    }
    
    func openAdvert(advert: Post) {
        let newVC = MainViewController()
        newVC.setProps(post: advert)
        self.navigationController?.pushViewController(newVC, animated: true)
    }
    
    func contactSeller(type: CarFooterCell.FooterContact) {
        switch type {
        case .chat:
            self.openComments()
        case .call:
            self.callUser()
        }
    }
    
    func openHistory() {
        let vc = AutoCheckViewController()
        vc.vin = mainViewModel.post.car.carNumber?.vin
        self.navigationController?.pushViewController(vc, animated: true)
    }
    
    func openFullInfo() {
        let vc = CarInfoViewController()
        vc.setProps(post: mainViewModel.post)
        self.navigationController?.pushViewController(vc, animated: true)
    }
}


// MARK: - Complaint View

extension MainViewController: ComplaintViewDelegate {
    
    func gotError(error: RequestError) {
        switch error {
        case .general:
            self.showAlert("Упс...", "Неизвестная ошибка")
        case .parameter(let msg):
            self.showAlert("Упс...", msg)
        }
        self.complaintView.removeFromSuperview()
        self.menuPopup.isHidden = false
    }
    
    func closeComplaintView() {
        self.hidePopup()
        self.complaintView.removeFromSuperview()
        self.menuPopup.isHidden = false
    }
}


// MARK: - UI

extension MainViewController {
    
    private func addViews () {
        view.addSubview(tableView)
        view.addSubview(overlayView)
        view.addSubview(spinnerView)
        
        addIntiallyPopup()
        self.hidePopup()
        
        tableView.snp.makeConstraints { (make) in
            make.top.bottom.equalTo(view.safeAreaLayoutGuide)
            make.leading.trailing.equalToSuperview()
        }
        
        overlayView.snp.makeConstraints { (make) in
            make.top.bottom.equalTo(view.safeAreaLayoutGuide)
            make.leading.trailing.equalToSuperview()
        }
        
        spinnerView.snp.makeConstraints { (make) in
            make.center.equalToSuperview()
        }
    }
    
    private func addIntiallyPopup () {
        let frame = CGRect(x: view.frame.width/2, y: 8, width: 216, height: 152)
        menuPopup = MenuPopup(frame: frame)
        overlayView.addSubview(menuPopup)
        menuPopup.addButtons(buttons: mainViewModel.menuItems)
    }
    
    private func showPopup () {
        NotificationCenter.default.addObserver(self, selector: #selector(didSelectMenuItem(notification:)), name: NSNotification.Name(rawValue: "menuClick"), object: nil)
        self.overlayView.isHidden = false
        screenGesture = UITapGestureRecognizer(target: self, action: #selector(overlayDidTap(sender:)))
        overlayView.addGestureRecognizer(screenGesture!)
    }
    
    private func hidePopup () {
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "menuClick"), object: nil)
        self.overlayView.isHidden = true
        if let t = screenGesture {
            self.overlayView.removeGestureRecognizer(t)
        }
    }
    
    private func showComplaintView () {
        self.view.addSubview(complaintView)
        self.view.bringSubviewToFront(complaintView)
        
        if let t = screenGesture {
            overlayView.removeGestureRecognizer(t)
        }
        self.hidePopup()
        self.overlayView.isHidden = false
        self.menuPopup.isHidden = true
        
        complaintView.snp.makeConstraints { (make) in
            make.bottom.equalTo(view.safeAreaLayoutGuide)
            make.leading.trailing.equalToSuperview()
           // make.height.equalTo(375)
        }
    }

    private func registerCells (table: UITableView) {
        table.register(CarHeaderCell.self, forCellReuseIdentifier: "CarHeaderCell")
        table.register(CarInfoCell.self, forCellReuseIdentifier: "CarInfoCell")
        table.register(CarDescriptionCell.self, forCellReuseIdentifier: "CarDescriptionCell")
        table.register(CarContactsCell.self, forCellReuseIdentifier: "CarContactsCell")
        table.register(SimilarAdsCell.self, forCellReuseIdentifier: "SimilarAdsCell")
        table.register(CarFooterCell.self, forCellReuseIdentifier: "CarFooterCell")
        table.register(CarHelperCell.self, forCellReuseIdentifier: "CarHelperCell")
        table.register(CarWarnCell.self, forCellReuseIdentifier: "CarWarnCell")
        table.register(CarHistoryCell.self, forCellReuseIdentifier: "CarHistoryCell")
        table.register(CarPriceCell.self, forCellReuseIdentifier: "CarPriceCell")
    }
}


// MARK: - Navigation Bar

extension MainViewController {
    
    private func setUpNav () {
        
        if (mainViewModel.isPreview) {
            self.addCloseIcon()
            self.navigationItem.title = "Предпросмотр"
        } else {
            self.addBackBtn()
            self.addPostNavBtns()
        }
        
        self.navigationItem.largeTitleDisplayMode = mainViewModel.isPreview ? .always : .never
        self.navigationController?.navigationBar.isHidden = false
    }
    
    private func addPostNavBtns () {
        let likeButton = UIBarButtonItem(image: UIImage(named: "like"), style: .plain, target: self, action: #selector(navBtnClicked(sender:)))
        likeButton.tintColor = mainViewModel.post.isLiked ? .blue : .greyColor
        likeButton.tag = 1
        
        let shareButton = UIBarButtonItem(image: UIImage(named: "share"), style: .plain, target: self, action: #selector(navBtnClicked(sender:)))
        shareButton.tintColor = .greyColor
        shareButton.tag = 2
        
        let moreButton = UIBarButtonItem(image: UIImage(named: "menu"), style: .plain, target: self, action: #selector(navBtnClicked(sender:)))
        moreButton.tintColor = .greyColor
        moreButton.tag = 3
        self.navigationItem.rightBarButtonItems = [moreButton, shareButton, likeButton]
    }
    
    
    private func addCloseIcon () {
        let closeBarBnt = UIBarButtonItem(image: UIImage(named: "dismiss"), style: .plain, target: self, action: #selector(navBtnClicked(sender:)))
        closeBarBnt.tintColor = .greyColor
        closeBarBnt.tag = 4
        self.navigationItem.rightBarButtonItem = closeBarBnt
    }
    
    private func addBackBtn () {
        let backButton = UIBarButtonItem(image: UIImage(named: "cancel"), style: .plain, target: self, action: #selector(navBtnClicked(sender:)))
        backButton.tintColor = .greyColor
        backButton.tag = 0
        
        self.navigationItem.hidesBackButton = true
        self.navigationItem.leftBarButtonItem = backButton
    }
}
